/*
 *HTTPManager.java
 *
 * Copyright(c) IronOne Technologies (Pvt) Ltd.  All Rights Reserved.
 * This software is the proprietary information of IronOne Technologies (Pvt) Ltd.
 *
 */
package com.ironone.streaming.comm;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.ironone.streaming.R;
import com.ironone.streaming.application.FormObject;
import com.ironone.streaming.application.MainApplication;
import com.ironone.streaming.model.EventsDataModel;
import com.ironone.streaming.model.OurShowsDataModel;
import com.ironone.streaming.model.RequestDataModel;
import com.ironone.streaming.model.ResponseDataModel;

/**
 * {This class handles the http connection}
 * 
 * @Created on Apr 22, 2013 : 1:07:59 PM
 * @author Suren Manawatta
 */
public class HTTPManager {
	String xml;
	Context context;

	// Set the timeout in milliseconds until a connection is established.
	// The default value is zero, that means the timeout is not used.
	// previous val: 10000
	int con_timeout = 10000;

	// Set the default socket timeout (SO_TIMEOUT) 
	// in milliseconds which is the timeout for waiting for data.
	// previous val: 15000
	int so_timeout = 12000;

	public HTTPManager(Context context) {
		this.context = context;
	}


	/**
	 * @return This method request XML from the server and returns it
	 * @throws TimeoutException 
	 */
	public ResponseDataModel getXmlFromUrl() {
		try {
			//return new HttpMnagerAsync().execute().get(con_timeout, TimeUnit.MILLISECONDS);
			MyTaskParams params = new MyTaskParams(xml, null);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method request JSON from the server and returns it
	 * @throws TimeoutException 
	 */
	public ResponseDataModel getInitServiceData(){
		try{
			String initUrl = new URL(context).getInitializeSvcURL();
			String apikey = context.getResources().getString(R.string.apikey);
			int dataVer = FormObject.getInstance().getDataVersion();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("api_key", apikey));
			nameValuePairs.add(new BasicNameValuePair("data_ver", Integer.toString(dataVer)));
			MyTaskParams params = new MyTaskParams(initUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method send facebook user data to the server
	 * @throws TimeoutException
	 */
	public ResponseDataModel sendFacebookUserData(){
		try{
			String loginUrl = new URL(context).getLoginSvcURL();
			String accessToken = FormObject.getInstance().getAccessToken();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));
			nameValuePairs.add(new BasicNameValuePair("name", FormObject.getInstance().getFbName()));
			nameValuePairs.add(new BasicNameValuePair("fb_id", FormObject.getInstance().getFbUserId()));
			nameValuePairs.add(new BasicNameValuePair("email", FormObject.getInstance().getFbEmail()));
			nameValuePairs.add(new BasicNameValuePair("birthday", FormObject.getInstance().getFbBirthday()));
			nameValuePairs.add(new BasicNameValuePair("location", FormObject.getInstance().getFbLocation()));
			nameValuePairs.add(new BasicNameValuePair("gender", FormObject.getInstance().getFbGender()));
			nameValuePairs.add(new BasicNameValuePair("mobile", ""));
			nameValuePairs.add(new BasicNameValuePair("page_like", FormObject.getInstance().getFbMusicLiked()));

			MyTaskParams params = new MyTaskParams(loginUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method get our shows data from the server
	 * @throws TimeoutException
	 */
	public ResponseDataModel getOurShowsData(){
		try{
			String showsUrl = new URL(context).getShowsSvcURL();
			String accessToken = FormObject.getInstance().getAccessToken();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));

			MyTaskParams params = new MyTaskParams(showsUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method get events data from the server
	 * @throws TimeoutException
	 */
	public ResponseDataModel getEventsData(){
		try {
			String eventsUrl = new URL(context).getEventsSvcURL();
			String accessToken = FormObject.getInstance().getAccessToken();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));

			MyTaskParams params = new MyTaskParams(eventsUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method get now playing data from the server
	 * @throws TimeoutException
	 */
	public ResponseDataModel getNowPlayingData() {
		try {
			String nowPlayingUrl = new URL(context).getNowPlayingSvcURL();
			String accessToken = FormObject.getInstance().getAccessToken();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));

			MyTaskParams params = new MyTaskParams(nowPlayingUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}

	/**
	 * @return This method get server date and time data from the server
	 * @throws TimeoutException
	 */
	public ResponseDataModel getDateTimeData() {
		try {
			String timeUrl = new URL(context).getTimeSvcURL();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);

			MyTaskParams params = new MyTaskParams(timeUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}


	public List<OurShowsDataModel> downloadOurShowsImages(Activity act, List<OurShowsDataModel> showData){
		for (OurShowsDataModel ourShowsDataModel : showData) {
			try {
				if(ourShowsDataModel.imageLink != null){
					//Option 1
					BitmapFactory.Options options = new BitmapFactory.Options();
					options.inSampleSize = 2;
					byte[] img = MainApplication.getBitmapToByteArr(BitmapFactory.decodeStream(ourShowsDataModel.imageLink.openConnection().getInputStream(), null, options));
					ourShowsDataModel.image = img;

					//Option 2
					/*BitmapFactory.Options options = new BitmapFactory.Options();
					options.inJustDecodeBounds = true;
					InputStream imgStream = ourShowsDataModel.imageLink.openConnection().getInputStream();
					Bitmap bitmap = BitmapFactory.decodeStream(imgStream, null, options);
					//int imageHeight = options.outHeight;
					int imageWidth = options.outWidth;
					//String imageType = options.outMimeType;

					// Recreate the stream
					options.inJustDecodeBounds = false;
					int sSize = (int)(imageWidth / scrnWidthNeeded);
					if (sSize <= 0)	sSize = 1;
					options.inSampleSize = 2;
					ourShowsDataModel.image = BitmapFactory.decodeStream(imgStream, null, options);*/
				}
			} catch (Exception e) {
				ourShowsDataModel.image = null;
				continue;
			}
		}
		return showData;
	}

	public List<EventsDataModel> downloadEventsImages(Activity act, List<EventsDataModel> eventsData) {
		for (EventsDataModel ourEventsDataModel : eventsData) {	
			try {
				if(ourEventsDataModel.imageLink != null){
					//Option 1
					BitmapFactory.Options options = new BitmapFactory.Options();
					options.inSampleSize = 2;

					byte[] img = MainApplication.getBitmapToByteArr(BitmapFactory.decodeStream(ourEventsDataModel.imageLink.openConnection().getInputStream(), null, options));
					ourEventsDataModel.image = img;

					//Option 2
					/*BitmapFactory.Options options = new BitmapFactory.Options();
					options.inJustDecodeBounds = true;
					InputStream imgStream = ourShowsDataModel.imageLink.openConnection().getInputStream();
					Bitmap bitmap = BitmapFactory.decodeStream(imgStream, null, options);
					//int imageHeight = options.outHeight;
					int imageWidth = options.outWidth;
					//String imageType = options.outMimeType;

					// Recreate the stream
					options.inJustDecodeBounds = false;
					int sSize = (int)(imageWidth / scrnWidthNeeded);
					if (sSize <= 0)	sSize = 1;
					options.inSampleSize = 2;
					ourShowsDataModel.image = BitmapFactory.decodeStream(imgStream, null, options);*/
				}
			} catch (Exception e) {
				ourEventsDataModel.image = null;
				continue;
			}
		}
		return eventsData;
	}

	public void downloadAlbumArtImage(Activity act, java.net.URL imageLink) {
		try {
			if(imageLink != null){
				//Option 1
				BitmapFactory.Options options = new BitmapFactory.Options();
				options.inSampleSize = 2;

				Bitmap temp = BitmapFactory.decodeStream((imageLink).openConnection().getInputStream(), null, options);
				if(temp == null && FormObject.getInstance().getAlbumArtImage() != null)
					FormObject.getInstance().setAlbumArtImage(FormObject.getInstance().getAlbumArtImage());
				else
					FormObject.getInstance().setAlbumArtImage(MainApplication.getBitmapToByteArr(temp));

				//Option 2
				/*BitmapFactory.Options options = new BitmapFactory.Options();
					options.inJustDecodeBounds = true;
					InputStream imgStream = ourShowsDataModel.imageLink.openConnection().getInputStream();
					Bitmap bitmap = BitmapFactory.decodeStream(imgStream, null, options);
					//int imageHeight = options.outHeight;
					int imageWidth = options.outWidth;
					//String imageType = options.outMimeType;

					// Recreate the stream
					options.inJustDecodeBounds = false;
					int sSize = (int)(imageWidth / scrnWidthNeeded);
					if (sSize <= 0)	sSize = 1;
					options.inSampleSize = 2;
					ourShowsDataModel.image = BitmapFactory.decodeStream(imgStream, null, options);*/
			}
		} catch (Exception e) {
			FormObject.getInstance().setAlbumArtImage(null);
		}
	}



	public ResponseDataModel sendRequestData(RequestDataModel rdm) {
		try{
			String reqUrl = new URL(context).getRequestSvcURL();
			String accessToken = FormObject.getInstance().getAccessToken();
			String tnlId = FormObject.getInstance().getTNLId();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));
			nameValuePairs.add(new BasicNameValuePair("tnl_id", tnlId));

			//nameValuePairs.add(new BasicNameValuePair("show_name", rdm.reqesterName));
			nameValuePairs.add(new BasicNameValuePair("requester_name", rdm.reqesterName));
			nameValuePairs.add(new BasicNameValuePair("song_name", rdm.songName));
			nameValuePairs.add(new BasicNameValuePair("song_artist", rdm.artist));
			nameValuePairs.add(new BasicNameValuePair("dedication", rdm.dedication));

			MyTaskParams params = new MyTaskParams(reqUrl, nameValuePairs);

			//return new HttpMnagerAsync().execute(params).get(con_timeout, TimeUnit.MILLISECONDS);
			return HttpMnagerExecute(params);
		} catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}
	}


	/*public class HttpMnagerAsync extends AsyncTask<MyTaskParams, Void, ResponseDataModel> {

		@Override
		protected ResponseDataModel doInBackground(MyTaskParams... params) {

			ResponseDataModel resDataModel = new ResponseDataModel();
			InputStream inputStream = null;
			BufferedReader reader = null;
			try {
				//Thread.sleep(3000);
				String URL = params[0].URL;
				List<NameValuePair> nvp = params[0].nameValuePairs;

				HttpParams paramss = new BasicHttpParams();
				HttpConnectionParams.setConnectionTimeout(paramss, so_timeout);
				HttpConnectionParams.setSoTimeout(paramss, so_timeout);

				HttpPost httpPost = new HttpPost(URL); //context.getResources().getString(R.string.url)
				httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
				httpPost.setEntity(new UrlEncodedFormEntity(nvp));

				DefaultHttpClient httpClient = new DefaultHttpClient();				
				HttpResponse httpResponse = httpClient.execute(httpPost);
				HttpEntity httpEntity = httpResponse.getEntity();
				inputStream = httpEntity.getContent();

				// JSON is UTF-8 by default
				reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
				StringBuilder sb = new StringBuilder();

				String line = null;
				while ((line = reader.readLine()) != null)
				{ sb.append(line + "\n"); }

				resDataModel.responseData = new JSONObject(sb.toString());
				return resDataModel;
			} catch(IOException io){
				return errorHandler(context.getString(R.string.error_io));
			}catch (JSONException jo) {
				return errorHandler(context.getString(R.string.error_jsonexception));
			}
			catch (Exception e) {
				return errorHandler(context.getString(R.string.error_general));
			}finally {
				try {
					if(inputStream != null)	inputStream.close();
					if(reader != null) reader.close();
				} catch (Exception e) { e.printStackTrace(); }
			}
		}

		@Override
		protected void onPostExecute(ResponseDataModel mod) {
		}
	}*/

	/**
	 * @return This method get server data behalf of all other functions
	 * @throws ConnectTimeoutException
	 * @throws IOException
	 * @throws JSONException
	 * @throws Exception
	 */
	private ResponseDataModel HttpMnagerExecute(MyTaskParams... params){
		ResponseDataModel resDataModel = new ResponseDataModel();
		InputStream inputStream = null;
		BufferedReader reader = null;
		try {
			//Thread.sleep(3000);
			String URL = params[0].URL;
			List<NameValuePair> nvp = params[0].nameValuePairs;

			HttpParams paramss = new BasicHttpParams();

			// Set the timeout in milliseconds until a connection is established.
			// The default value is zero, that means the timeout is not used. 
			HttpConnectionParams.setConnectionTimeout(paramss, con_timeout);

			// Set the default socket timeout (SO_TIMEOUT) 
			// in milliseconds which is the timeout for waiting for data.
			HttpConnectionParams.setSoTimeout(paramss, so_timeout);

			HttpPost httpPost = new HttpPost(URL); //context.getResources().getString(R.string.url)
			httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
			httpPost.setEntity(new UrlEncodedFormEntity(nvp));

			DefaultHttpClient httpClient = new DefaultHttpClient();				
			HttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			inputStream = httpEntity.getContent();

			// JSON is UTF-8 by default
			reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
			StringBuilder sb = new StringBuilder();

			String line = null;
			while ((line = reader.readLine()) != null)
			{ sb.append(line + "\n"); }

			resDataModel.responseData = new JSONObject(sb.toString());
			return resDataModel;

		}catch (ConnectTimeoutException e){
			return errorHandler(context.getString(R.string.error_timeout));
		}catch(IOException io){
			return errorHandler(context.getString(R.string.error_io));
		}catch (JSONException jo) {
			return errorHandler(context.getString(R.string.error_jsonexception));
		}catch (Exception e) {
			return errorHandler(context.getString(R.string.error_general));
		}finally {
			try {
				if(inputStream != null)	inputStream.close();
				if(reader != null) reader.close();
			} catch (Exception e) { 
				e.printStackTrace(); 
			}
		}
	}


	private ResponseDataModel errorHandler(String errMsg) {
		ResponseDataModel resDataModel = new ResponseDataModel();
		resDataModel.isError = true;
		resDataModel.errorMessage = errMsg;
		resDataModel.responseData = null;
		return resDataModel;
	}

	private static class MyTaskParams {
		String URL = "";
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

		MyTaskParams(String pURL, List<NameValuePair> nvPairs) {
			this.URL = pURL;
			this.nameValuePairs = nvPairs;
		}
	}

}